﻿// Fill out your copyright notice in the Description page of Project Settings.

#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "Camera/CameraComponent.h"
#include "Camera/CameraActor.h"
#include "Components/SphereComponent.h"
#include "Engine/CanvasRenderTarget2D.h"
#include "Engine/TextureRenderTarget2D.h"
#include "Components/SceneCaptureComponent2D.h"
#include "PixcelProduct.h"
#include "ConvolutionBox.h"
#include "Control.h"
#include "zhouyi/zhouyilab.h"
#include "Pathjudge.h"
#include "DrawPath.h"
#include "WifiClient.h"
#include "Json.h"
#include "Json/Public/Serialization/JsonSerializer.h"
#include "Json/Public/Serialization/JsonReader.h"
#include <UObject/ObjectMacros.h>
#include "car.generated.h"



struct RenderFormat
{
	EPixelFormat Pixfomat;
	int Width;
	int Hight;
};

UENUM(BlueprintType)
enum class UpdataPixelFormat : uint8
{
	GREY        UMETA(DisplayName = "灰度图"),
	BOOL        UMETA(DisplayName = "二值化图"),
	TESTBOX		UMETA(DisplayName = "卷积核测试")
};

UENUM(BlueprintType)
enum class DenoiseConfig : uint8
{
	NONE					UMETA(DisplayName = "无"),
	MEDIANDENOISE			UMETA(DisplayName = "中值滤波"),
	SHELLMEANNOISE			UMETA(DisplayName = "加壳均值滤波"),
	NOSHELLMEANNOISE        UMETA(DisplayName = "无壳均值滤波")
};


UENUM(BlueprintType)
enum class CenterLineConfig : uint8
{
	ORDINARY			UMETA(DisplayName = "普通方法"),
	DX					UMETA(DisplayName = "边线变化率寻找法"),
	BORADFIND_CALCUALTE UMETA(DisplayName = "边界寻找计算法")
};


UENUM(BlueprintType)
enum class ConvolutionBoxConfig : uint8
{
	NONE					UMETA(DisplayName = "无"),
	CROSS_LOWER_LEFT		UMETA(DisplayName = "十字左下角"),
	CROSS_LOWER_RIGHT		UMETA(DisplayName = "十字右下角"),
	CROSS_HIGH_LEFT			UMETA(DisplayName = "十字左上角"),
	CROSS_HIGH_RIGHT		UMETA(DisplayName = "十字右上角"),
	ISLAND_LEFT			    UMETA(DisplayName = "左环岛"),
	ISLAND_RIGHT			UMETA(DisplayName = "右环岛"),
	TRIGEMINAL_LOWER_LEFT	UMETA(DisplayName = "三叉左下"),
	TRIGEMINAL_LOWER_RIGHT	UMETA(DisplayName = "三叉右下"),
	TRIGEMINAL_MID			UMETA(DisplayName = "三叉中间"),
};


UENUM(BlueprintType)
enum class SceanEelem : uint8
{
	NONE					UMETA(DisplayName = "无"),
	FORK					UMETA(DisplayName = "三叉"),
	CARREFOUR				UMETA(DisplayName = "十字"),
	ROUNDABOUT_LEFT			UMETA(DisplayName = "左环岛"),
	ROUNDABOUT_RIGHT		UMETA(DisplayName = "右环岛"),
	START_PONINT			UMETA(DisplayName = "起点"),
};


UENUM(BlueprintType)
enum class WifiMode : uint8
{
	NONE					UMETA(DisplayName = "无"),
	CAMERA					UMETA(DisplayName = "摄像头"),
	VAR						UMETA(DisplayName = "变量"),
	ICM						UMETA(DisplayName = "陀螺仪"),
	
};




UCLASS()
class SMARTCAR1_API Acar : public ACharacter
{
	GENERATED_BODY()

public:
	// Sets default values for this character's properties
	Acar();

protected:

	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "图像配置|相机", meta = (AllowPrivateAccess = "true"))
		USceneCaptureComponent2D* SceneCamera;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "图像配置|Texture2D")
		UTexture2D* Texture2D;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "图像配置|DrawBorder")
		UTexture2D* DrawBorder;


	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "图像配置", DisplayName = "UI图像选择")
		UpdataPixelFormat UIPixelFormat = UpdataPixelFormat::BOOL;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "图像配置", DisplayName = "直方均值化")
		bool histogramAverageConfig = false;



	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "图像配置|二值化图像处理", DisplayName = "阀值")
		uint8 threshold = 0;



	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "图像配置|降噪", DisplayName = "噪声大小")
		int NoiseNumber = 0;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "图像配置|降噪", DisplayName = "降噪方法")
		DenoiseConfig denoiseConfig = DenoiseConfig::NONE;



	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "图像配置|卷积核测试设置", DisplayName = "卷积核阈左值")
		int SpeicalPointthresholdMin = 0;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "图像配置|卷积核测试设置", DisplayName = "卷积核阈右值")
		int SpeicalPointthresholdMax = 255;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "图像配置|卷积核测试设置", DisplayName = "卷积核选择")
		ConvolutionBoxConfig ConvolutionBoxChose = ConvolutionBoxConfig::NONE;
	ConvolutionBoxConfig LastConfig = ConvolutionBoxConfig::NONE;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "图像配置|卷积核测试设置", DisplayName = "卷积核原图像选择")
		UpdataPixelFormat ConvolutionBoxSrcChose = UpdataPixelFormat::BOOL;



	RenderFormat SceneCameraFormat;
	FTexture2DMipMap* mip;
	UTexture2D* Cameradata;

	FTexture2DMipMap* DrawBordermip;
	void* DrawBordermipataPtr;
	uint8* DrawBorderARR;

	/*************************************************图像数据区*************************************************************************/
	void* MipdataPtr;
	uint8* GreyImageData;
	uint8* boolImageData;
	uint8* ConvolutedImageData;
	uint8* ImageBuf;
	uint8* finalImage;



	uint8* CenterLineARR;
	uint8* LeftBorderLineARR;
	uint8* RightBorderLineARR;
	short* LeftBorderArrD;
	short* RightBorderArrD;

	BorderLineInfo My_BorderLineInfo;

	int CenterLineLenth;
	/*************************************************图像数据区*************************************************************************/


	/*************************************************智能车参数*************************************************************************/
	CarParameter My_CarParameter = {
		{200.0,150.0,45.0,0.0,68,64.0},
		{0.0},
		{0.0},
		{0,0,0,30,4096},
		{0},
		{0},
		0
	};

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|中线", DisplayName = "中线寻找方式")
		CenterLineConfig CenterLinefindConfig = CenterLineConfig::ORDINARY;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|中线", DisplayName = "中线颜色")
		FColor CenterlineColor = FColor(255, 0, 0);
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|中线", DisplayName = "左边线颜色")
		FColor LeftBorderlineColor = FColor(0, 255, 0);
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|中线", DisplayName = "右边线颜色")
		FColor RightBorderlineColor = FColor(0, 0, 255);

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|道路判断", DisplayName = "三叉")
		bool IsFork = 0;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|道路判断", DisplayName = "左环岛")
		bool IsLeftAroundAbout = 0;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|道路判断", DisplayName = "右环岛")
		bool IsRightAroundAbout = 0;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|道路判断", DisplayName = "起点")
		bool IsStart = 0;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|道路判断", DisplayName = "十字")
		bool IsCarrefour = 0;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|道路判断", DisplayName = "直行")
		bool IsKeepStraightFlag = 0;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|道路判断", DisplayName = "扫描区域显示")
		SceanEelem My_SceanEelem = SceanEelem::NONE;


	//前后轮距 mm 
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|车辆参数", DisplayName = "前后轮距")
		float FrontBack_WheelBase = 200.0;
	//左右轮距 mm
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|车辆参数", DisplayName = "左右轮距")
		float LeftRight_WheelBase = 150.0;
	//当前转向角度
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "控制部分|车辆参数", DisplayName = "当前转向角度")
		float CurrentTurnAng;
	//前进速度 速度为(mm/s)
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "控制部分|车辆参数", DisplayName = "当前前进速度")
		float MoveSpeed;
	//转向速度 转向角速度(Rad/s)
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "控制部分|车辆参数", DisplayName = "当前转向速度")
		float TurnSpeed;
	//左轮速度
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "控制部分|车辆参数", DisplayName = "左轮编码器")
		int LeftEncoder;
	//右轮速度
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "控制部分|车辆参数", DisplayName = "右轮编码器")
		int RightEncoder;
	UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = "控制部分|车辆参数", DisplayName = "速度Pid预设置编码器值")
		int PidEncoder;

	/// <summary>
	/// 更新车辆参数
	/// </summary>
	void UpdateCarParameter();
	/*************************************************智能车参数*************************************************************************/


	/*************************************************控制部分*************************************************************************/
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分", DisplayName = "是否开启自动控制")
		bool IsStartControl = 0;

	PID_normal_Struct Pid_Normal = { 0.8,0,0.1,0.0,0.0,45.0,-45.0 };

	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|普通PID", DisplayName = "普通P")
		float NormalP = 0.8;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|普通PID", DisplayName = "普通I")
		float NormalI = 0.0;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "控制部分|普通PID", DisplayName = "普通D")
		float NormalD = 0.1;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "控制部分", DisplayName = "误差")
		float Err = 0.0;
	UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "控制部分", DisplayName = "PID输出")
		float Output = 0.0;

	void Control();

	void CarTurn();

	void DrawScanArea(const uint8 FirstPointX, const uint8 FirstPointY, const uint8 SecondPointX, const uint8 SecondPointY,
		const uint8* ImageArr, const int SizeX, const int SizeY, ScanMode_enum ScanMode);

	void DrawScanAreaTogether(ScanAreaCB* My_ScanAreaCB, const int ScanAreaNum, const uint8* ImageArr, const int SizeX, const int SizeY);

	void ShowScanArea();

	fockCB forkCB1 = { 400,0,0 };
	CarrefourCB CarrefourCB1 = { 0 };
	RoundAbutCBLeft RoundAbutCBLeft1 = { 0 };
	RoundAbutCBRight RoundAbutCBRight1 = { 0 };

	/*************************************************控制部分*************************************************************************/

	/*************************************************网络部分*************************************************************************/
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "网络部分", DisplayName = "服务器IP地址")
		FString ServerIp = "192.168.31.42";
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "网络部分", DisplayName = "服务器端口")
		int ServerPort = 9999;
	UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "网络部分", DisplayName = "连接模式")
		WifiMode Wifi_Mode = WifiMode::NONE;

	WifiClient* Clent;
	SendImageInit_CB ImageDataInfo;
	SendVarInit_CB VarInfo;
	SendIcmInit_CB IcmInfo;

	float* VarBuf;
	uint8** lineBuf;
	float IcmBuf[3];

	
	

	/*************************************************网络部分*************************************************************************/





	// Called when the game starts or when spawned
	virtual void BeginPlay() override;
	//前进
	void MoveForward(float val);
	//向右走
	void MoveRight(float val);
	//转向
	void TurnRight(float val);
	//获取数据
	void GetCameraData();
	//创建纹理
	void Updata2DRGBA8();

	//二值化图像操作
	void BoolViewUpdata();

	//系统配置
	void Config();

	//最终更新
	void UpdateFinalImage();

	//降噪
	void denoise();

	//卷积核测试
	void ConvolutedImageTest();

	//路径判断
	void Pathjudge();


	void DrawPoint(uint8* DrawBorderarr, const int SizeX, const int SizeY, const int PointX, const int PointY, FColor PointColor);

public:
	// Called every frame
	virtual void Tick(float DeltaTime) override;

	// Called to bind functionality to input
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;

};
